#pragma once

#include <functional>
#include <memory>
#include <sys/epoll.h>

#include "noncopyable.h"
#include "Timestamp.h"
#include "Logger.h"

class EventLoop;

/**
 * Channel理解为通道，封装了sockfd和其感兴趣的事件以及
 * 处理时间的回调函数
*/
class Channel : public noncopyable
{
public:
    using EventCallback = std::function<void()>;
    using ReadEventCallback = std::function<void(Timestamp)>;

    Channel(EventLoop* loop, int fd);
    ~Channel();

    // Poller检测到fd的事件就绪后，Channel就会调用该函数进行事件处理
    void handleEvent(Timestamp receiveTime);

    // 设置回调函数对象
    void setReadCallback(ReadEventCallback cb) { readCallback_ = std::move(cb); }
    void setWriteCallback(EventCallback cb) { writeCallback_ = std::move(cb); }
    void setCloseCallback(EventCallback cb) { closeCallback_ = std::move(cb); }
    void setErrorCallback(EventCallback cb) { errorCallback_ = std::move(cb); }

    // 防止Channel被手动remove掉，Channel还在执行回调操作
    void tie(const std::shared_ptr<void>&);

    int fd() const { return fd_; }
    int events() const { return events_; }
    void set_revents(int revents) { revents_ = revents; }

    // 设置fd相应的事件状态
    // enableReading让fd对读事件感兴趣
    // update函数底层调用的是epoll_ctl
    void enableReading() { events_ |= kReadEvent; update(); }
    void disableReading() { events_ &= ~kReadEvent; update(); }
    void enableWriting() { events_ |= kWriteEvent; update(); }
    void disableWriting() { events_ &= ~kWriteEvent; update(); }
    void disableAll() { events_ = kNoneEvent; update(); }

    // 返回fd当前的事件状态
    bool isNoneEvent() const { return events_ == kNoneEvent; }
    bool isWriting() const { return events_ & kWriteEvent; }
    bool isReading() const { return events_ & kReadEvent; }

    // 由Poller进行调用
    int index() const { return index_; }
    void set_index(int index) { index_ = index; }

    // 返回当前Channel所属的EventLoop，one loop per thread
    EventLoop* ownerLoop() { return loop_; }
    // 将当前的Channel从其所属的EventLoop中移除
    void remove();

private:
    void update();
    void handleEventWithGuard(Timestamp receiveTime);

    static const int kNoneEvent;
    static const int kReadEvent;
    static const int kWriteEvent;

    EventLoop* loop_; // Channel所属的事件循环
    const int fd_; // fd，Poller监听的对象
    int events_; // fd感兴趣的事件
    int revents_; // fd上具体发生的事件，由Poller进行通知
    int index_;  // 表示fd的状态

    std::weak_ptr<void> tie_;
    bool tied_;

    // fd感兴趣的事件发生后，会根据发生的事件类型执行下面对应的回调函数
    ReadEventCallback readCallback_;
    EventCallback writeCallback_;
    EventCallback closeCallback_;
    EventCallback errorCallback_;
};